package com.sfx.concurrent.demo.concurrent.Singleton;

import org.springframework.objenesis.instantiator.util.UnsafeUtils;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: sfx
 * Date: 2023-03-17
 * Time: 15:37
 */
public class Test {
    /**
     * 饿汉式
     * 枚举饿汉式
     * 懒汉式
     * 双重检验锁DCL 懒汉式
     * 静态内部类 懒汉式
     * JDK哪些场景用到了 单例模式 ?
     * System类下 :
     *     GC方法 和 exit方法(Runtime类) --> 饿汉式
     *     Console类  --> 双检锁懒汉式单例
     * Collections类下 :
     * 以Empty打头的类
     *      EmptyNavigableSet --> 静态内部类懒汉式单例
     *      EmptyIterator  --> 静态内部类懒汉式单例
     *      EmptyList  --> 饿汉单例
     * ReverseComparator --> 静态内部类懒汉式单例
     * ReverseComparator的reversed方法  --> 枚举类饿汉式
     */
    public static void main1(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
        Singleton1.otherMethod();
        System.out.println("===========================================");
        System.out.println(Singleton1.getINSTANCE());
        //reflection(Singleton1.class);
        //serializable(Singleton1.getINSTANCE());
        unsafe(Singleton1.class);
    }

    public static void main2(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
        Singleton2.otherMethod();
        System.out.println("===========================================");
        System.out.println(Singleton2.getINSTANCE());
        //reflection(Singleton2.class);
        //serializable(Singleton2.getINSTANCE());
        unsafe(Singleton2.class);
    }

    public static void main(String[] args) {
        Singleton3.otherMethod();
        System.out.println("===========================================");
        System.out.println(Singleton3.getInstance());
    }

    //1.通过反射来破坏单例
    public static void reflection(Class<?> singleton1Class) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Constructor<?> constructor = singleton1Class.getDeclaredConstructor();
        constructor.setAccessible(true);
        System.out.println("反射创建单例对象 : " + constructor.newInstance());
    }

    /**
     * 序列化的操作流程
     *      内存对象转换为字节码形式
     *      字节码通过IO输出流写入到磁盘中
     * 反序列化
     *      持久化的字节码内容，通过IO输入流读到内存中
     *      将内存对象转换为Java对象
     */
    //2.反序列化破坏单例
    public static void serializable(Object instance) throws IOException, ClassNotFoundException {
        //ByteArrayOutputStream类流在内存中创建缓冲区，并且发送到流的所有数据都存储在缓冲区中。
        ByteArrayOutputStream bos = new ByteArrayOutputStream();//字节数组输出流
        //Java.io.ObjectOutputStream 类将 Java 对象的原始数据类型和图形写入 OutputStream
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        //该方法将指定的对象写入 ObjectOutputStream。
        oos.writeObject(instance);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        System.out.println("反序列化创建单例 : " + ois.readObject());//把字节流还原出一个对象
    }
    //3.unsafe破坏单例-->暂时没有解决方法
    public static void unsafe(Class<?> clazz) throws InstantiationException {
        Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);
        System.out.println("unsafe破坏单例 : " + o);
    }
}